package com.storm.util

import com.storm.cache.AuthCacheManager
import com.storm.config.JwtTokenComponent
import com.storm.model.JwtUser
import com.storm.util.inter.TokenFilterInterface
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.filter.OncePerRequestFilter
import java.lang.Exception
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 * 进行登入校验
 */
class DefaultTokenFilter(
    private val jwtTokenComponent: JwtTokenComponent,
    private val authCacheManager: AuthCacheManager,
    //从db中获取 如果有 先保存到缓存中再返回
    private val getByDB: (String) -> UserDetails,
) : TokenFilterInterface, OncePerRequestFilter() {
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        //先从header中取，后续添加更多地方 eg cookie
        val token: String? = request.getHeader("token") ?: request.getHeader("cookie")

        val username = jwtTokenComponent.getUsername(token)
        do {
            //token无效
            if (username.isNullOrBlank()) {
                break
            }
            val tokens = authCacheManager.getTokensByUser(username)
            val currentToken = tokens.find { it.token==token }
            //token失效
            if (jwtTokenComponent.isUnUseful(currentToken)) {
                break
            }
            //使用自定义类，保存缓存信息
            val jwtUser: JwtUser = try {
                (authCacheManager.getJwtUser(username) ?: getByDB(username)) as JwtUser
            } catch (e: Exception) {
                log.error("通过token获取用户出错{}", e.message, e)
                break
            }
            if (jwtUser.isnull()) {
                break
            }
            authCacheManager.saveJwtUser(jwtUser, 60 * 60 * 24L)
            val authentication = UsernamePasswordAuthenticationToken(
                jwtUser, null, jwtUser.authorities
            )
            SecurityContextHolder.getContext().authentication = authentication
        } while (false)
        filterChain.doFilter(request, response)
    }

}